home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 August (Alt) / CHIP 2005-08.1.iso / program / guvenlik / syslinux-3.07.exe / mtools / syslinux.c < prev    next >
Encoding:
C/C++ Source or Header  |  2005-01-03  |  6.7 KB  |  295 lines

  1. #ident "$Id: syslinux.c,v 1.6 2005/01/04 03:27:43 hpa Exp $"
  2. /* ----------------------------------------------------------------------- *
  3.  *   
  4.  *   Copyright 1998-2004 H. Peter Anvin - All Rights Reserved
  5.  *
  6.  *   This program is free software; you can redistribute it and/or modify
  7.  *   it under the terms of the GNU General Public License as published by
  8.  *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  9.  *   Boston MA 02111-1307, USA; either version 2 of the License, or
  10.  *   (at your option) any later version; incorporated herein by reference.
  11.  *
  12.  * ----------------------------------------------------------------------- */
  13.  
  14. /*
  15.  * syslinux.c - Linux installer program for SYSLINUX
  16.  *
  17.  * This program now requires mtools.  It turned out to be a lot
  18.  * easier to deal with than dealing with needing mount privileges.
  19.  * We need device write permission anyway.
  20.  */
  21.  
  22. #define _XOPEN_SOURCE 500    /* Required on glibc 2.x */
  23. #define _BSD_SOURCE
  24. #include <alloca.h>
  25. #include <errno.h>
  26. #include <fcntl.h>
  27. #include <inttypes.h>
  28. #include <mntent.h>
  29. #include <paths.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <syslog.h>
  34. #include <unistd.h>
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37. #include <sys/wait.h>
  38.  
  39. #include "syslinux.h"
  40. #include "libfat.h"
  41.  
  42. char *program;            /* Name of program */
  43. char *device;            /* Device to install to */
  44. pid_t mypid;
  45. off_t filesystem_offset = 0;    /* Offset of filesystem */
  46.  
  47. void __attribute__((noreturn)) usage(void)
  48. {
  49.   fprintf(stderr, "Usage: %s [-sf] [-o offset] device\n", program);
  50.   exit(1);
  51. }
  52.  
  53. void __attribute__((noreturn)) die(const char *msg)
  54. {
  55.   fprintf(stderr, "%s: %s\n", program, msg);
  56.   exit(1);
  57. }
  58.  
  59. /*
  60.  * read/write wrapper functions
  61.  */
  62. ssize_t xpread(int fd, void *buf, size_t count, off_t offset)
  63. {
  64.   char *bufp = (char *)buf;
  65.   ssize_t rv;
  66.   ssize_t done = 0;
  67.  
  68.   while ( count ) {
  69.     rv = pread(fd, bufp, count, offset);
  70.     if ( rv == 0 ) {
  71.       die("short read");
  72.     } else if ( rv == -1 ) {
  73.       if ( errno == EINTR ) {
  74.     continue;
  75.       } else {
  76.     die(strerror(errno));
  77.       }
  78.     } else {
  79.       bufp += rv;
  80.       offset += rv;
  81.       done += rv;
  82.       count -= rv;
  83.     }
  84.   }
  85.  
  86.   return done;
  87. }
  88.  
  89. ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
  90. {
  91.   const char *bufp = (const char *)buf;
  92.   ssize_t rv;
  93.   ssize_t done = 0;
  94.  
  95.   while ( count ) {
  96.     rv = pwrite(fd, bufp, count, offset);
  97.     if ( rv == 0 ) {
  98.       die("short write");
  99.     } else if ( rv == -1 ) {
  100.       if ( errno == EINTR ) {
  101.     continue;
  102.       } else {
  103.     die(strerror(errno));
  104.       }
  105.     } else {
  106.       bufp += rv;
  107.       offset += rv;
  108.       done += rv;
  109.       count -= rv;
  110.     }
  111.   }
  112.  
  113.   return done;
  114. }
  115.  
  116. /*
  117.  * Version of the read function suitable for libfat
  118.  */
  119. int libfat_xpread(intptr_t pp, void *buf, size_t secsize, libfat_sector_t sector)
  120. {
  121.   off_t offset = (off_t)sector * secsize + filesystem_offset;
  122.   return xpread(pp, buf, secsize, offset);
  123. }
  124.  
  125.  
  126. int main(int argc, char *argv[])
  127. {
  128.   static unsigned char sectbuf[512];
  129.   int dev_fd;
  130.   struct stat st;
  131.   int status;
  132.   char **argp, *opt;
  133.   int force = 0;        /* -f (force) option */
  134.   char mtools_conf[] = "/tmp/syslinux-mtools-XXXXXX";
  135.   int mtc_fd;
  136.   FILE *mtc, *mtp;
  137.   struct libfat_filesystem *fs;
  138.   libfat_sector_t s, *secp, sectors[65]; /* 65 is maximum possible */
  139.   int32_t ldlinux_cluster;
  140.   int nsectors;
  141.   const char *errmsg;
  142.  
  143.   (void)argc;            /* Unused */
  144.  
  145.   mypid = getpid();
  146.   program = argv[0];
  147.   
  148.   device = NULL;
  149.  
  150.   for ( argp = argv+1 ; *argp ; argp++ ) {
  151.     if ( **argp == '-' ) {
  152.       opt = *argp + 1;
  153.       if ( !*opt )
  154.     usage();
  155.  
  156.       while ( *opt ) {
  157.     if ( *opt == 's' ) {
  158.       syslinux_make_stupid();    /* Use "safe, slow and stupid" code */
  159.     } else if ( *opt == 'f' ) {
  160.       force = 1;        /* Force install */
  161.     } else if ( *opt == 'o' && argp[1] ) {
  162.       filesystem_offset = (off_t)strtoull(*++argp, NULL, 0); /* Byte offset */
  163.     } else {
  164.       usage();
  165.     }
  166.     opt++;
  167.       }
  168.     } else {
  169.       if ( device )
  170.     usage();
  171.       device = *argp;
  172.     }
  173.   }
  174.  
  175.   if ( !device )
  176.     usage();
  177.  
  178.   /*
  179.    * First make sure we can open the device at all, and that we have
  180.    * read/write permission.
  181.    */
  182.   dev_fd = open(device, O_RDWR);
  183.   if ( dev_fd < 0 || fstat(dev_fd, &st) < 0 ) {
  184.     perror(device);
  185.     exit(1);
  186.   }
  187.  
  188.   if ( !force && !S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode) ) {
  189.     fprintf(stderr, "%s: not a block device or regular file (use -f to override)\n", device);
  190.     exit(1);
  191.   }
  192.  
  193.   xpread(dev_fd, sectbuf, 512, filesystem_offset);
  194.   
  195.   /*
  196.    * Check to see that what we got was indeed an MS-DOS boot sector/superblock
  197.    */
  198.   if( (errmsg = syslinux_check_bootsect(sectbuf)) ) {
  199.     die(errmsg);
  200.   }
  201.  
  202.   /*
  203.    * Create an mtools configuration file
  204.    */
  205.   mtc_fd = mkstemp(mtools_conf);
  206.   if ( mtc_fd < 0 || !(mtc = fdopen(mtc_fd, "w")) ) {
  207.     perror(program);
  208.     exit(1);
  209.   }
  210.   fprintf(mtc,
  211.       "MTOOLS_NO_VFAT=1\n"
  212.       "MTOOLS_SKIP_CHECK=1\n" /* Needed for some flash memories */
  213.       "drive s:\n"
  214.       "  file=\"/proc/%lu/fd/%d\"\n"
  215.       "  offset=%llu\n",
  216.       (unsigned long)mypid,
  217.       dev_fd,
  218.       (unsigned long long)filesystem_offset);
  219.   fclose(mtc);
  220.   
  221.   /*
  222.    * Run mtools to create the LDLINUX.SYS file
  223.    */
  224.   if ( setenv("MTOOLSRC", mtools_conf, 1) ) {
  225.     perror(program);
  226.     exit(1);
  227.   }
  228.  
  229.   /* This command may fail legitimately */
  230.   system("mattrib -h -r -s s:ldlinux.sys 2>/dev/null");
  231.  
  232.   mtp = popen("mcopy -D o -D O -o - s:ldlinux.sys", "w");
  233.   if ( !mtp ||
  234.        (fwrite(syslinux_ldlinux, 1, syslinux_ldlinux_len, mtp) 
  235.     != syslinux_ldlinux_len) ||
  236.        (status = pclose(mtp), !WIFEXITED(status) || WEXITSTATUS(status)) ) {
  237.     die("failed to create ldlinux.sys");
  238.   }
  239.  
  240.   status = system("mattrib +r +h +s s:ldlinux.sys");
  241.  
  242.   if ( !WIFEXITED(status) || WEXITSTATUS(status) ) {
  243.     fprintf(stderr,
  244.         "%s: warning: failed to set system bit on ldlinux.sys\n",
  245.         program);
  246.   }
  247.  
  248.   unlink(mtools_conf);
  249.  
  250.   /*
  251.    * Now, use libfat to create a block map
  252.    */
  253.   fs = libfat_open(libfat_xpread, dev_fd);
  254.   ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL);
  255.   secp = sectors;
  256.   nsectors = 0;
  257.   s = libfat_clustertosector(fs, ldlinux_cluster);
  258.   while ( s && nsectors < 65 ) {
  259.     *secp++ = s;
  260.     nsectors++;
  261.     s = libfat_nextsector(fs, s);
  262.   }
  263.   libfat_close(fs);
  264.  
  265.   /*
  266.    * Patch ldlinux.sys and the boot sector
  267.    */
  268.   syslinux_patch(sectors, nsectors);
  269.  
  270.   /*
  271.    * Write the now-patched first sector of ldlinux.sys
  272.    */
  273.   xpwrite(dev_fd, syslinux_ldlinux, 512, filesystem_offset + ((off_t)sectors[0] << 9));
  274.  
  275.   /*
  276.    * To finish up, write the boot sector
  277.    */
  278.  
  279.   /* Read the superblock again since it might have changed while mounted */
  280.   xpread(dev_fd, sectbuf, 512, filesystem_offset);
  281.  
  282.   /* Copy the syslinux code into the boot sector */
  283.   syslinux_make_bootsect(sectbuf);
  284.  
  285.   /* Write new boot sector */
  286.   xpwrite(dev_fd, sectbuf, 512, filesystem_offset);
  287.  
  288.   close(dev_fd);
  289.   sync();
  290.  
  291.   /* Done! */
  292.  
  293.   return 0;
  294. }
  295.